﻿using DocumentFormat.OpenXml.Lite.Helper;
using DocumentFormat.OpenXml.Lite.Interfaces;
using DocumentFormat.OpenXml.Lite.Shared;
using DocumentFormat.OpenXml.Lite.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace DocumentFormat.OpenXml.Lite.SpreadsheetML.Excel.WorksheetElements
{
    [XmlRoot("row", Namespace = Constants.ExcelMain)]
    public class Row : XmlSerializable, ICopyable
    {
        #region Attributes

        [Optional]
        [XmlAttribute("r", Form = XmlSchemaForm.Qualified)]
        public Nullable<uint> Index { get; set; }

        [Optional]
        [XmlAttribute("spans", Form = XmlSchemaForm.Qualified)]
        public string Spans { get; set; }

        [Optional]
        [XmlAttribute("s", Form = XmlSchemaForm.Qualified)]
        public Nullable<uint> StyleIndex { get; set; }

        [Optional]
        [XmlAttribute("customFormat", Form = XmlSchemaForm.Qualified)]
        public Nullable<bool> CustomFormat { get; set; }

        [Optional]
        [XmlAttribute("ht", Form = XmlSchemaForm.Qualified)]
        public Nullable<double> RowHeight { get; set; }

        [Optional]
        [XmlAttribute("hidden", Form = XmlSchemaForm.Qualified)]
        public Nullable<bool> Hidden { get; set; }

        [Optional]
        [XmlAttribute("customHeight", Form = XmlSchemaForm.Qualified)]
        public Nullable<double> CustomHeight { get; set; }

        [Optional]
        [XmlAttribute("outlineLevel", Form = XmlSchemaForm.Qualified)]
        public Nullable<byte> OutlineLevel { get; set; }

        [Optional]
        [XmlAttribute("collapsed", Form = XmlSchemaForm.Qualified)]
        public Nullable<bool> Collapsed { get; set; }

        [Optional]
        [XmlAttribute("thickTop", Form = XmlSchemaForm.Qualified)]
        public Nullable<bool> ThickTop { get; set; }

        [Optional]
        [XmlAttribute("thickBot", Form = XmlSchemaForm.Qualified)]
        public Nullable<bool> ThickBottom { get; set; }

        [Optional]
        [XmlAttribute("ph", Form = XmlSchemaForm.Qualified)]
        public Nullable<bool> ShowPhonetic { get; set; }

        #endregion

        [XmlElement("c", Namespace = Constants.ExcelMain)]
        public XmlList<Cell> Cells { get; set; }

        /// <summary>
        /// Future Feature Data Storage Area
        /// </summary>
        [Optional]
        [XmlElement("extLst", Namespace = Constants.ExcelMain)]
        public ExtensionList ExtList { get; set; }

        [XmlIgnore]
        public Cell this[int i]
        {
            get
            {
                Cell column = Cells.FirstOrDefault(r => r.Index == i);
                if (column != null)
                {
                    return column;
                }

                if (Cells.Count > i)
                {
                    return Cells[i];
                }

                throw new IndexOutOfRangeException();
            }
            set
            {
                Cell column = Cells.FirstOrDefault(r => r.Index == i);
                if (column != null)
                {
                    column.Copy(value);
                }
                else if (Cells.Count > i)
                {
                    Cells[i].Copy(value);
                }
                else
                {
                    throw new IndexOutOfRangeException();
                }
            }
        }

        public Row() 
        {
            Cells = new XmlList<Cell>();
        }

        public Cell AddCell()
        {
            Cell c = new Cell() { Parent = this };
            Cells.Add(c);
            return c;
        }

        public Cell CreateCell(uint index)
        {
            Cell c = new Cell() { Parent = this };
            c.Index = (int)index;
            Cells.Add(c);
            if (c.Index != Cells.Count)
            {
                Cells.Sort(delegate(Cell c1, Cell c2)
                {
                    int c1i = c1.Index == -1 ? Cells.IndexOf(c1) : c1.Index;
                    int c2i = c2.Index == -1 ? Cells.IndexOf(c2) : c2.Index;
                    if (c1i < c2i) return -1;
                    if (c1i == c2i) return 0;
                    return 1;
                });
            }
            return c;
        }

        public void Copy(object obj)
        {
            if (obj is Row)
            {
                this.Collapsed = (obj as Row).Collapsed;
                this.Cells = (obj as Row).Cells;
                this.CustomFormat = (obj as Row).CustomFormat;
                this.CustomHeight = (obj as Row).CustomHeight;
                this.ExtList = (obj as Row).ExtList;
                this.Hidden = (obj as Row).Hidden;
                this.Index = (obj as Row).Index;
                this.OutlineLevel = (obj as Row).OutlineLevel;
                this.RowHeight = (obj as Row).RowHeight;
                this.ShowPhonetic = (obj as Row).ShowPhonetic;
                this.Spans = (obj as Row).Spans;
                this.StyleIndex = (obj as Row).StyleIndex;
                this.ThickBottom = (obj as Row).ThickBottom;
                this.ThickTop = (obj as Row).ThickTop;
            }
        }
    }
}
